package Netty.NIO;

import javax.swing.*;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * 多路复用
 *
 * @author hecai
 * @date 2021/11/13
 */
public class MultipleNioServer {

    public static void main(String[] args) throws IOException {
        // 创建NIO服务
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        // 设置非阻塞
        serverSocketChannel.configureBlocking(false);
        // 创建Selector选择器 进行 多路复用器
        Selector selector = Selector.open();

        // 将NIO服务注册到selector选择器中，并注册accept事件
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        // 绑定端口 启动服务
        ServerSocket socket = serverSocketChannel.socket();
        socket.bind(new InetSocketAddress(9090));
        System.out.println("启动成功");

        while (true) {
            // 启动selector 选择器 阻塞，直到事件通知才会返回
            int num = selector.select();
            if (num == 0) {
                continue;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();

                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = ((ServerSocketChannel) selectionKey.channel()).accept();
                    // 设置非阻塞
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("收到新连接：" + socketChannel);
                } else if (selectionKey.isReadable()) { // 客户端连接有数据可以读时触发
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer requestBuffer = ByteBuffer.allocate(1024);

                    while (socketChannel.isOpen() && socketChannel.read(requestBuffer) != 1) {
                        try {
                            // 长连接情况下 ，需要手动判断数据有没有读取结束
                            if (requestBuffer.position() > 0) {
                                // 简单判断   超过0个字节就认为读取结束
                                break;
                            }
                            // 如果没有数据就不继续后面的处理
                            if (requestBuffer.position() == 0) {
                                continue;
                            }
                            requestBuffer.flip();

                            byte[] contents = new byte[requestBuffer.remaining()];
                            requestBuffer.get(contents);
                            System.out.println(new String(contents));
                            System.out.println("收到数据，来自：" + socketChannel.getRemoteAddress());
                            // TODO 业务操作 数据库 调用接口

                            // 响应结果
                            String response = "HTTP/1.1 200 OK\r\n" +
                                    "Content-Length: 11 \r\n" +
                                    "Hello World";
                            ByteBuffer wrap = ByteBuffer.wrap(response.getBytes());
                            while (wrap.hasRemaining()) {
                                socketChannel.write(wrap);
                            }
                        } catch (Exception e) {

                        }
                    }
                }
            }

        }


    }

}
